/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "StdAfx.h"
#include "Particle.h"
#include "IEmitter.h"
#include "Timer.h"

namespace particlesystem {

Particle::Particle()
:	m_iState(PARTICLE_DEAD)
{
}

Particle::~Particle(void)
{
}

#define SLERP(A, B, T) (A*(1-T) + B*T)

bool Particle::update(float ft)
{
	static float t;
	// Return if the particle is already dead
	if (m_iState == PARTICLE_DEAD) return false;

	// Increase the lifetime
	t = 1 - static_cast<float>((pEmitter->m_dPartMaxLifetime - m_sData.fPartTime)/pEmitter->m_dPartMaxLifetime);
	m_sData.fPartTime += ft;

	// Kill the particle if the maxlifetime is reached and return
	if (m_sData.fPartTime >= pEmitter->m_dPartMaxLifetime) {
		m_iState = PARTICLE_DEAD;
		--pEmitter->m_iNumAlive;
		return false;
	}

	m_vVelocity += pEmitter->m_fPartWeight * IEmitter::vGravity * ft;

	// Add position and change color transparency
	m_sData.vPosition += m_vVelocity*ft;
	m_sData.vColor = SLERP(pEmitter->m_vPartInitColor, pEmitter->m_vPartFadeColor, t);
	m_sData.fSize = SLERP(pEmitter->m_fPartMinSize, pEmitter->m_fPartMaxSize, t);

	return true;
}

const int Particle::getState() const
{
	return m_iState;
}

void Particle::create(IEmitter *emitter)
{
	pEmitter = emitter;	

	math::Vector3 randVel = math::Vector3( -pEmitter->m_fHalfVar + pEmitter->m_fVariance*rand()/(float)RAND_MAX, 
										   -pEmitter->m_fHalfVar + pEmitter->m_fVariance*rand()/(float)RAND_MAX, 
										   -pEmitter->m_fHalfVar + pEmitter->m_fVariance*rand()/(float)RAND_MAX );
	// Get the initial values from the emitter
	m_iState = PARTICLE_ALIVE;
	m_sData.fPartTime = 0;
	m_sData.vPosition = pEmitter->getOffset() * pEmitter->m_pSpawnTrans->getMatrix();
	m_sData.vInitPosition = m_sData.vPosition;
	m_vVelocity = pEmitter->m_vInitialVelocity + randVel;

	//m_sData.vColor = math::Vector4(rand()/(float)RAND_MAX, rand()/(float)RAND_MAX, rand()/(float)RAND_MAX, rand()/(float)RAND_MAX);
	m_sData.vColor = pEmitter->m_vPartInitColor;
	m_sData.fSize = pEmitter->m_fPartMinSize -pEmitter->m_fPartSizeVar/2.0f + pEmitter->m_fPartSizeVar*rand()/(float)RAND_MAX;
	++pEmitter->m_iNumAlive;
}

} // namespace
